<template>
    <div class="common-padding">
        <!-- 搜索框 -->
        <lemon-search :form-model="searchFormModel" :style="searchStyle" :form-label-width="searchFormLabelWidth" :form-size="searchFormSize" :form-item="searchFormItem" :show-search="showSearch" :show-add="showAdd" :show-clear="showClear" :show-expand="showExpand" :search-permission="searchPermission" :add-permission="addPermission" @on-search="onSearch" @on-add="onAdd">
            <!-- 搜索框插槽，传递给子组件使用 -->
            <template #items>
                <slot name="searchItems"></slot>
            </template>
            <!-- 定义两个按钮插槽，传递给子组件使用 -->
            <template #frontBtn>
                <slot name="searchFrontBtn"></slot>
            </template>
            <template #afterBtn>
                <slot name="searchAfterBtn"></slot>
            </template>
        </lemon-search>

        <!-- 数据表格 -->
        <lemon-table :data="isTree ? data : data?.content" :style="tableStyle" :height="tableHeight" :table-item="tableItem" :children="children" :is-tree="isTree" :show-info="showInfo" :show-edit="showEdit" :show-enable="showEnable" :show-unable="showUnable" :show-del="showDel" @on-info="onInfo" @on-edit="onEdit" @on-enable="onEnable" @on-unable="onUnable" @on-del="onDel">
            <!-- 定义表格列插槽，传递给子组件使用 -->
            <template #columns>
                <slot name="tableColumns"></slot>
            </template>
            <!-- 定义表格按钮插槽，传递给子组件使用 -->
            <template #frontBtn="scope">
                <slot name="tableFrontBtn" :row="scope.row"></slot>
            </template>
            <template #afterBtn="scope">
                <slot name="tableAfterBtn" :row="scope.row"></slot>
            </template>
        </lemon-table>

        <!-- 分页 -->
        <lemon-page :data="data" @on-size-change="onSizeChange" @on-current-change="onCurrentChange" />

        <!-- 弹出层 -->
        <lemon-dialog v-model="dialogShow" :dialog-title="dialogTitle" :dialog-footer="dialogFooter" @on-submit="onDialogSubmit" @on-cancel="onDialogCancel" @on-before-close="onDialogCancel">
            <lemon-form :form-model="dialogFormModel" :form-item="dialogFormItem" :style="dialogFormStyle" :form-label-width="dialogFormLabelWidth" class="lemon-form-class" :form-button="false" ref="dialogFormRef" />
        </lemon-dialog>
    </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, inject, watch, nextTick } from "vue";
import type { ComponentSize } from "element-plus";

//获取自定义全局方法
const { emitter, http, box } = inject<any>("method");

//排序
interface Sort {
    asc: string[] | null;
    desc: string[] | null;
}

//父传子
interface Props {
    //请求的路径
    uri: string;

    //排序规则
    sort?: Sort | null;

    //搜索框数据
    searchFormModel?: Record<string, any>;
    searchCondition?: Record<string, string>; //搜索条件
    searchStyle?: Record<string, any>;
    searchFormLabelWidth?: string;
    searchFormSize?: ComponentSize;
    searchFormItem?: Record<string, any>;
    showSearch?: boolean;
    showClear?: boolean;
    showAdd?: boolean;
    showExpand?: boolean;
    searchPermission?: string;
    addPermission?: string;

    //数据表格数据
    tableStyle?: Record<string, any>;
    tableHeight?: string | number;
    tableItem?: Array<any>;
    showInfo?: boolean;
    showEdit?: boolean;
    showEnable?: boolean;
    showUnable?: boolean;
    showDel?: boolean;
    infoPermission?: string;
    editPermission?: string;
    enablePermission?: string;
    unablePermission?: string;
    delPermission?: string;
    children?: string;
    isTree?: boolean;

    //弹出层数据
    dialogFormStyle?: Record<string, any>;
    dialogFormLabelWidth?: string;
    dialogInfoFormModel?: Record<string, any>;
    dialogInfoFormItem?: Record<string, any>;
    dialogEditFormModel?: Record<string, any>;
    dialogEditFormItem?: Record<string, any>;
    dialogAddFormModel?: Record<string, any>;
    dialogAddFormItem?: Record<string, any>;
}
const props = withDefaults(defineProps<Props>(), {
    //请求的路径
    uri: "",

    //排序规则
    sort: null,

    //搜索框数据
    searchFormModel: () => ({}),
    searchCondition: () => ({}),
    searchStyle: () => ({}),
    searchFormLabelWidth: "80px",
    searchFormSize: "default",
    searchFormItem: () => ({}),
    showSearch: true,
    showClear: true,
    showAdd: true,
    showExpand: true,
    searchPermission: "PAGE",
    addPermission: "INSERT",

    //数据表格数据
    tableStyle: () => ({}),
    tableHeight: "calc(100vh - 196px)",
    tableItem: () => [],
    showInfo: true,
    showEdit: true,
    showEnable: true,
    showUnable: true,
    showDel: true,
    infoPermission: "FINDBYID",
    editPermission: "UPDATE",
    enablePermission: "ENABLE",
    unablePermission: "UNABLE",
    delPermission: "DELETEBYID",
    children: "children",
    isTree: false,

    // 弹出层数据
    dialogFormStyle: () => ({}),
    dialogFormLabelWidth: "80px",
    dialogInfoFormModel: () => ({}),
    dialogInfoFormItem: () => ({}),
    dialogEditFormModel: () => ({}),
    dialogEditFormItem: () => ({}),
    dialogAddFormModel: () => ({}),
    dialogAddFormItem: () => ({}),
});

//双向绑定的数据data
const data = defineModel<any>({ default: null });

//处理父组件传入的uri（去掉前后/）
const uri = props?.uri ? props?.uri.replace(/^\/+|\/+$/g, "") : "";

//弹出框form表单数据
const dialogFormModel = reactive<any>({});

//弹出框form表单子项
const dialogFormItem = reactive<any>({});

//弹出层弹窗标题
const dialogTitle = ref("");

//是否展示弹窗
const dialogShow = ref<boolean>(false);

//弹出框底部按钮展示
const dialogFooter = ref<boolean>(false);

//弹框form表单组件
const dialogFormRef: any = ref(null);

//分页信息（页码，分页数量）
const page = reactive({
    pageNum: 1,
    pageSize: 10,
});

onMounted(() => init());

//处理请求参数
const getParams = (param: any = {}) => {
    const searchForm = { ...props.searchFormModel };
    //如果有搜索条件，则转换请求数据
    if (props?.searchCondition) {
        Object.keys(searchForm)
            .filter((key: string) => Object.keys(props.searchCondition).includes(key))
            .forEach((key: string) => (searchForm[key] = { [props.searchCondition[key]]: searchForm[key] }));
    }
    return { ...page, ...props.sort, param: { ...searchForm, ...param } };
};

//初始化函数
const init = async (param: any = {}): Promise<void> => {
    if (props.isTree) {
        data.value = await http.get(`${uri}/find`, { ...props.searchFormModel, ...param });
    } else {
        data.value = await http.get(`${uri}/page`, getParams(param));
    }
};

//搜索
const onSearch = () => {
    page.pageNum = 1;
    init();
};

//要提示的字段
const tips: Array<string> = ["name", "title"];

//添加
const onAdd = (): void => {
    emit("onAdd");
    dialogFooter.value = true;
    dialogTitle.value = "添加";
    dialogShow.value = true;
    Object.assign(dialogFormModel, props.dialogAddFormModel);
    Object.assign(dialogFormItem, props.dialogAddFormItem);
    //清空数据
    Object.keys(dialogFormModel).forEach((item: any) => {
        if (Array.isArray(dialogFormModel[item])) {
            dialogFormModel[item] = [];
        } else {
            dialogFormModel[item] = null;
        }
    });
};

//详情
const onInfo = async (row: any) => {
    emit("onInfo", row);
    dialogFooter.value = false;
    dialogTitle.value = "详情";
    dialogShow.value = true;
    Object.assign(dialogFormModel, props.dialogInfoFormModel);
    Object.assign(dialogFormItem, props.dialogInfoFormItem);
    const data = await http.get(`${uri}/findById/${row.id}`);
    Object.keys(dialogFormModel).forEach((item: any) => (dialogFormModel[item] = data[item]));
};

//编辑
const onEdit = async (row: any) => {
    emit("onEdit", row);
    dialogFooter.value = true;
    dialogTitle.value = "编辑";
    dialogShow.value = true;
    Object.assign(dialogFormModel, props.dialogEditFormModel);
    Object.assign(dialogFormItem, props.dialogEditFormItem);
    const data = await http.get(`${uri}/findById/${row.id}`);
    Object.keys(dialogFormModel).forEach((item: any) => (dialogFormModel[item] = data[item]));
};

//执行提交
const onDialogSubmit = async () => {
    if (!dialogFormRef.value?.formRef()) return;
    const status = await dialogFormRef.value?.formRef().validate((valid: any, _fields: any) => valid);
    if (status) {
        let data;
        if (dialogFormModel?.id) {
            data = await http.put(`${uri}/update`, dialogFormModel);
        } else {
            data = await http.post(`${uri}/insert`, dialogFormModel);
        }
        if (data.success) {
            emitter.emit("msg-success", data?.data);
            onDialogCancel();
            init();
        }
    }
};

//取消弹窗
const onDialogCancel = () => {
    emit("onDialogCancel");
    dialogFormRef.value?.resetFields();
    dialogShow.value = false;
    // 重置为空响应式对象
    for (const key in dialogFormModel) {
        delete dialogFormModel[key];
    }
    for (const key in dialogFormItem) {
        delete dialogFormItem[key];
    }
};

//启用
const onEnable = (row: any) =>
    box.confirm(`确定要启用${showTip(row)}吗？`, "启用", async () => {
        emit("onEnable", row);
        const data = await http.put(`${uri}/enable/${row.id}`);
        if (data?.success) {
            emitter.emit("msg-success", data?.data);
            init();
        }
    });

//停用
const onUnable = (row: any) =>
    box.confirm(`确定要停用${showTip(row)}吗？`, "停用", async () => {
        emit("onUnable", row);
        const data = await http.put(`${uri}/unable/${row.id}`);
        if (data?.success) {
            emitter.emit("msg-success", data?.data);
            init();
        }
    });

//删除
const onDel = (row: any) =>
    box.confirm(`确定要删除${showTip(row)}吗？`, "删除", async () => {
        emit("onDel", row);
        const data = await http.delete(`${uri}/deleteById/${row.id}`);
        if (data?.success) {
            emitter.emit("msg-success", data?.data);
            init();
        }
    });

//分页->改变分页数量
const onSizeChange = (val: number) => {
    page.pageNum = 1;
    page.pageSize = val;
    init();
};

//分页->改变页码
const onCurrentChange = (val: number) => {
    page.pageNum = val;
    init();
};

//返回要提示的字段
const showTip = (row: any): string => {
    for (let key of Object.keys(row)) {
        for (let item of tips) {
            if (key.toLowerCase().includes(item)) {
                return `<font color="red" style="font-weight:bold">${row[key]}</font>`;
            }
        }
    }
    return "这条数据";
};

//使用defineEmits注册一个自定义事件
const emit = defineEmits(["onDialogShow", "init", "onAdd", "onInfo", "onEdit", "onEnable", "onUnable", "onDel", "onDialogCancel"]);

//监听把弹窗信息告诉父组件
watch(dialogShow, () => nextTick(() => emit("onDialogShow", dialogShow.value)));

//把方法暴露给父组件使用
defineExpose({
    init: init,
    add: onAdd,
    info: onInfo,
    edit: onEdit,
    enable: onEnable,
    unable: onUnable,
    del: onDel,
    page: () => page,
    search: () => props.searchFormModel,
    params: getParams,
});
</script>

<style scoped lang="less">
@import "@/assets/less/common.less";
</style>
